「這條規則重要,我在記憶裡記一份,順手也寫進 skill 裡,兩邊都有總比漏掉好吧?」
聽起來是在加保險,實際上是在埋一顆定時炸彈。今天用一個案例,講清楚為什麼「同一條規則寫兩份」比「只寫一份、但沒寫全」還要危險——因為前者會讓 AI 表現得時好時壞,而你完全不知道為什麼。
有一條規則是「commit 訊息要用 Conventional Commits 格式,<type>(<scope>): <描述>」。這條規則一開始寫進了記憶系統裡的專案筆記,方便 AI 每次 commit 前查一下格式;後來為了讓規則更容易被自動套用,又把同一條規則寫進了一支 skill 的內文裡,兩邊的描述幾乎一模一樣。
幾個月後,團隊決定調整規則:破壞性變更要在 type 後面加 ! 標記,例如 feat!(api): 移除舊版端點。負責更新的人只記得改了 skill 裡的版本,忘了記憶系統裡那份筆記其實也寫著同一條規則的舊版本。
從那之後,AI 的行為變得不可預期:有時候 commit 訊息會正確加上 !,有時候不會。追查了很久才發現——AI 到底讀到哪個版本,取決於當下的任務情境先觸發了 skill 還是先讀到記憶,兩個都存在、內容卻不一致,AI 沒有辦法知道該相信哪一份。
如果這條規則從頭到尾只存在一個地方,不管是忘了更新還是根本沒寫,至少行為是一致的——要嘛全部都是舊格式,要嘛全部都沒有這條規則,問題很容易被發現、被指認出原因。
但「兩個地方各寫一份,只改了其中一份」造成的是間歇性、看似隨機的錯誤行為,這種錯誤最難排查,因為它不會每次都發生,復現条件也說不清楚,很容易被誤判成「AI 有時候就是會出錯」,而不是「規則的事實來源本身就有兩份互相打架的版本」。
用一組對照來看這個差異:
❌ 同一條規則寫在兩個地方:
記憶系統裡的專案筆記:
「commit 訊息用 Conventional Commits 格式,
<type>(<scope>): <描述>」
skill 裡的內文:
「commit 訊息用 Conventional Commits 格式,
破壞性變更要加 !,例如 feat!(api): ...」
→ 兩份內容不同步,AI 讀到哪一份看情境,
行為變得不可預測,而且很難第一時間意識到
問題出在「有兩個事實來源」
✅ 只在一個地方維護,另一處只留指標:
skill 裡的內文(唯一的事實來源):
「commit 訊息用 Conventional Commits 格式,
破壞性變更要加 !,例如 feat!(api): ...」
記憶系統裡的專案筆記:
「commit 訊息格式規則見對應的 skill,
不在這裡重複寫規則內容」
→ 規則只有一份,更新只需要改一個地方,
AI 不會讀到互相矛盾的版本
這正是這個系列反覆講的模式的另一種樣貌:工具沒有被設計成「唯一事實來源」的樣子,只是被當成「寫在哪裡都可以,反正 AI 看得到就好」,於是自然而然地退化成互相矛盾的雜訊。
事後補救的第一步,不是把兩份都改成最新版本,而是先決定這條規則到底該歸哪一層——判斷標準很直接:
像 commit 訊息格式這種「每次 commit 都適用的具體規則」,本質上屬於 skill/CLAUDE.md 該管的範圍,記憶系統不該重複收錄規則內容,只該收錄「這條規則是什麼時候、因為什麼理由被調整的」這種脈絡性資訊——這樣記憶系統跟 skill 各自負責不同的東西,就不會出現同一份規則被兩邊各自維護、各自漂移的狀況。
回想你手上正在用的 AI 協作工具:有沒有哪條規則,你自己也說不清楚它「正式」寫在哪裡——記憶裡有、skill 裡好像也有?如果現在要調整這條規則,你有把握改一個地方就夠了嗎?
明天要換一個角度:Skill 不只可以是文字規則,還可以附帶一支真正會執行的工具(script),把某些機械式檢查自動化——這件事怎麼決定「自動化到哪裡為止、哪裡一定要人工」。